from functools import wraps
from flask_jwt_extended import get_jwt_identity

from app.models import AuthRole, BlogUser, AuthPermission
from app.error import AuthRoleError, AuthPermissionError
from . import service


def has_role(roles: set[str], super_user=False, error_msg='没有权限访问'):
    """登录角色校验装饰器
    roles：校验权限
    super_user：超级用户是否校验，默认False不验证
    raise AuthRoleError：角色校验异常
    """

    def decorator(func):
        @wraps(func)
        def inner(*args, **kwargs):
            user_id = get_jwt_identity()
            # 1.炒鸡用户不验证
            if super_user:
                user: BlogUser = BlogUser.query.get(user_id)
                if user and user.super_user:
                    return func(*args, **kwargs)
            # 2.传入验证的角色为空=不需要验证角色=直接通过
            if len(roles) <= 0:
                return func(*args, **kwargs)
            # 3.普通用户执行验证
            user_role: list[AuthRole] = service.user_role(user_id)
            if len(user_role) <= 0:
                # 没有任何角色=没有任何权限
                raise AuthRoleError(message=error_msg)
            # 4.用户拥有角色代码，判断传入的权限代码用户是否拥有
            user_role_code: list[str] = [record.role_code for record in user_role]
            # 只需要有一个满足就可以=判断是否有交集
            if len(roles.intersection(user_role_code)) > 0:
                ret = func(*args, **kwargs)
            else:
                raise AuthRoleError(message=error_msg)
            return ret

        return inner

    return decorator


def has_permission(codes: set[str], super_user=False, error_msg='没有权限访问'):
    """权限装饰器
    codes：校验权限代码
    super_user：超级用户是否校验，默认False不验证
    error_msg：错误提示消息
    raise AuthPermissionError：权限校验异常
    """

    def decorator(func):
        @wraps(func)
        def inner(*args, **kwargs):
            user_id = get_jwt_identity()
            # 1.炒鸡用户不验证
            if super_user:
                user: BlogUser = BlogUser.query.get(user_id)
                if user and user.super_user:
                    return func(*args, **kwargs)
            # 2.传入验证的权限为空=不需要验证权限=直接通过
            if len(codes) <= 0:
                return func(*args, **kwargs)
            # 3.普通用户执行验证
            user_permission: list[AuthPermission] = service.user_permission_all(user_id)
            if len(user_permission) <= 0:
                # 没有任何权限
                raise AuthPermissionError(message=error_msg)
            # 4.用户拥有角色代码，判断传入的权限代码用户是否拥有
            user_permission_code: list[str] = [record.p_code for record in user_permission]
            # 只需要有一个满足就可以=判断是否有交集
            if len(codes.intersection(user_permission_code)) > 0:
                ret = func(*args, **kwargs)
            else:
                raise AuthPermissionError(message=error_msg)
            return ret

        return inner

    return decorator
